home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / editors / ae92.zoo / eaea.c < prev    next >
C/C++ Source or Header  |  1992-05-27  |  13KB  |  711 lines

  1. ----eaea.c----
  2. /*
  3.  *    ae.c        Anthony's Editor  May '92
  4.  *
  5.  *    Public Domain 1991, 1992 by Anthony Howe.  All rights released.
  6.  */
  7.  
  8. #include <ctype.h>
  9. #include <curses.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12.  
  13. #ifndef BUF
  14. #define BUF    32767
  15. #endif /* BUF */
  16.  
  17. #ifndef HUP
  18. #define HUP    "ae.hup"
  19. #endif /* HUP */
  20.  
  21. #define HELP_LINE    7
  22.  
  23. typedef struct keytable_t {
  24.     int key;
  25.     void (*func)();
  26. } keytable_t;
  27.  
  28. int done;
  29. int row, col;
  30. int point, page, epage;
  31. int input;
  32. int helpline;
  33. char buf[BUF];
  34. char *ebuf;
  35. char *gap = buf;
  36. char *egap;
  37. char *filename;
  38. keytable_t *table;
  39.  
  40. /*
  41.  *    The following assertions must be maintained.
  42.  *
  43.  *    o  buf <= gap <= egap <= ebuf
  44.  *        If gap == egap then the buffer is full.
  45.  *
  46.  *    o  cursor = ptr(point) and cursor < gap or egap <= cursor 
  47.  *
  48.  *    o  page <= point < epage
  49.  *
  50.  *    o  0 <= point <= pos(ebuf) <= BUF
  51.  *
  52.  *
  53.  *    Memory representation of the file:
  54.  *
  55.  *        low    buf  -->+----------+
  56.  *                |  front   |
  57.  *                | of file  |
  58.  *            gap  -->+----------+<-- character not in file 
  59.  *                |   hole   |
  60.  *            egap -->+----------+<-- character in file
  61.  *                |   back   |
  62.  *                | of file  |
  63.  *        high    ebuf -->+----------+<-- character not in file 
  64.  *
  65.  *
  66.  *    point & gap
  67.  *
  68.  *    The Point is the current cursor position while the Gap is the 
  69.  *    position where the last edit operation took place. The Gap is 
  70.  *    ment to be the cursor but to avoid shuffling characters while 
  71.  *    the cursor moves it is easier to just move a pointer and when 
  72.  *    something serious has to be done then you move the Gap to the 
  73.  *    Point. 
  74.  *
  75.  *
  76.  *    Use of stdio for portability.
  77.  *
  78.  *    Stdio will handle the necessary conversions of text files to 
  79.  *    and from a machine specific format.  Things like fixed length 
  80.  *    records; CRLF mapping into <newline> (\n) and back again; 
  81.  *    null padding; control-Z end-of-file marks; and other assorted 
  82.  *    bizare issues that appear on many unusual machines.
  83.  *
  84.  *    AE is meant to be simple in both code and usage.  With that
  85.  *    in mind certain assumptions are made.
  86.  *
  87.  *    Reading:  If a file can not be opened, assume that it is a
  88.  *    new file.  If an error occurs, fall back to a safe state and
  89.  *    assume an empty file.  fread() is typed size_t which is an
  90.  *    unsigned number.  Zero (0) would indicate a read error or an
  91.  *    empty file.  A return value less than BUF is alright, since
  92.  *    we asked for the maximum allowed.
  93.  *
  94.  *    Writing:  If the file can not be opened or a write error occurs,
  95.  *    then we scramble and save the user's changes in a file called 
  96.  *    ae.hup.  If ae.hup fails to open or a write error occurs, then 
  97.  *    we assume that shit happens.
  98.  *
  99.  */
  100.  
  101. int adjust();
  102. int nextline();
  103. int pos();
  104. int prevline();
  105. int save();
  106. char *ptr();
  107.  
  108. void backsp();
  109. void bottom();
  110. void delete();
  111. void display();
  112. void down();
  113. void file();
  114. void help();
  115. void insert();
  116. void insert_mode();
  117. void left();
  118. void lnbegin();
  119. void lnend();
  120. void movegap();
  121. void pgdown();
  122. void pgup();
  123. void redraw();
  124. void right();
  125. void quit();
  126. void flip();
  127. void top();
  128. void up();
  129. void wleft();
  130. void wright();
  131.  
  132. #if TERMCAP
  133. /*
  134.  *    Function Key Support for BSD CURSES.
  135.  *
  136.  *    BSD CURSES does not support function keys as nicely as System V 
  137.  *    or XPG CURSES.  So I've provided some functions that can decode
  138.  *    multi-byte function keys that are commonly supported by BSD's
  139.  *    termcap file.
  140.  *
  141.  *    The KEY_xxxx macro constants are not defined in the same manner
  142.  *    as System V or XPG.  Also the key_table[] can be customised to
  143.  *    support additional key sequences that might not be supported by
  144.  *    termcap.  Create a new key code and provide the key sequence 
  145.  *    string; initkey() will not alter the provided sequence provided
  146.  *    it doesn't match a termcap capability name (see KEY_BACKSPACE).
  147.  */
  148.  
  149. #include <sys/types.h>
  150.  
  151. int initkey();
  152. int getkey();
  153.  
  154. #define KEY_DOWN        (-11)
  155. #define KEY_UP          (-12)
  156. #define KEY_LEFT        (-13)
  157. #define KEY_RIGHT       (-14)
  158. #define KEY_BACKSPACE   (-15)
  159. #define KEY_DC        (-16)
  160. #define KEY_F0          (-20)
  161. #define KEY_F(n)        (KEY_F0-(n))
  162.  
  163. typedef struct key_entry_t {
  164.     short code;
  165.     char *entry;
  166. } key_entry_t;
  167.  
  168. char key_buffer[1024];
  169.  
  170. key_entry_t key_table[] = {
  171.     { KEY_DOWN, "kd" },
  172.     { KEY_UP, "ku" },
  173.     { KEY_LEFT, "kl" },
  174.     { KEY_RIGHT, "kr" },
  175.     { KEY_BACKSPACE, "\b" },
  176.     { KEY_DC, "\177" },
  177.     { KEY_F(0), "k0" },
  178.     { KEY_F(1), "k1" },
  179.     { KEY_F(2), "k2" },
  180.     { KEY_F(3), "k3" },
  181.     { KEY_F(4), "k4" },
  182.     { KEY_F(5), "k5" },
  183.     { KEY_F(6), "k6" },
  184.     { KEY_F(7), "k7" },
  185.     { KEY_F(8), "k8" },
  186.     { KEY_F(9), "k9" },
  187.     { 0, NULL }
  188. };
  189.  
  190. int
  191. initkey()
  192. {
  193.     key_entry_t *k;
  194.     char *ptr, *kbuf, *tname;
  195.     static char buffer[1024];
  196.     
  197.     if ((tname = (char*) getenv("TERM")) == NULL 
  198.     || tgetent(buffer, tname) != 1)
  199.         return (0);
  200.     for (kbuf = key_buffer, k = key_table; k->entry != NULL; ++k) {
  201.         ptr = (char*) tgetstr(k->entry, &kbuf);
  202.         if (ptr != NULL)
  203.             k->entry = ptr;
  204.     }
  205.     return (1);
  206. }
  207.  
  208. int
  209. getkey()
  210. {
  211.     key_entry_t *k;
  212.     int submatch;
  213.     static char buffer[128];
  214.     static char *record = buffer;
  215.  
  216.     /* If recorded bytes remain, return next recorded byte. */
  217.     if (*record != '\0')
  218.         return (*record++);
  219.     /* Reset record buffer. */
  220.     record = buffer;
  221.     do {
  222.         /* Read and record one byte. */
  223.         *record++ = getch();
  224.         *record = '\0';
  225.  
  226.         /* If recorded bytes match any multi-byte sequence... */
  227.         for (k = key_table, submatch = 0; k->entry != NULL; ++k) {
  228.             char *p, *q; 
  229.             for (p = buffer, q = k->entry; *p == *q; ++p, ++q) {
  230.                 if (*p == '\0') {
  231.                     /* Return extended key code. */
  232.                     return (k->code);
  233.                 }
  234.             }
  235.             if (*p == '\0') {
  236.                 /* Recorded bytes match anchored substring. */
  237.                 submatch = 1;
  238.             }
  239.         }
  240.         /* If recorded bytes matched an anchored substring, loop. */
  241.     } while (submatch);
  242.     /* Return first recorded byte. */
  243.     record = buffer;
  244.     return (*record++);
  245. }
  246.  
  247. #else /* not TERMCAP */
  248.  
  249. #define initkey()    keypad(stdscr,1)
  250. #define getkey()    getch()
  251.  
  252. #endif /* TERMCAP */
  253.  
  254. /* ASCII Control Codes */
  255. #undef CTRL
  256. #define CTRL(x)        ((x) & 0x1f)
  257. #define DEL        0x7f
  258.  
  259. char help_ea[] = "\
  260. Left, right, up, down\tarrow keys\tBeginning and end of line\t^A ^D\n\
  261. Word left and right\t^W ^E\t\tTop and bottom of file\t\t^T ^B\n\
  262. Page up and down\t^P ^N\t\tDelete left and right\tbackspace DEL\n\
  263. Insert\t\t\ttyped keys\tHelp on and off\t\t\tF1\n\
  264. Save file\t\t^F\t\tRedraw\t\t\t\t^R\n\
  265. Quit\t\t\t^C\t\tFlip to VI-style\t\t^Z\n\
  266. ....5...10....5...20....5...30....5...40....5...50....5...60....5...70....5...80";
  267.  
  268. keytable_t modeless[] = {
  269.     { KEY_LEFT, left },
  270.     { KEY_RIGHT, right },
  271.     { KEY_DOWN, down },
  272.     { KEY_UP, up },
  273.     { CTRL('w'), wleft },
  274.     { CTRL('e'), wright },
  275.     { CTRL('n'), pgdown },
  276.     { CTRL('p'), pgup },
  277.     { CTRL('a'), lnbegin },
  278.     { CTRL('d'), lnend },
  279.     { CTRL('t'), top },
  280.     { CTRL('b'), bottom },
  281.     { KEY_BACKSPACE, backsp },
  282.     { '\b', backsp },
  283.     { KEY_DC, delete },
  284.     { DEL, delete },
  285.     { CTRL('f'), file },
  286.     { CTRL('r'), redraw },
  287.     { CTRL('c'), quit },
  288.     { CTRL('z'), flip },
  289.     { KEY_F(1), help },
  290.     { 0, insert }
  291. };
  292.  
  293. char help_ae[] = "\
  294. Left, right, up, down\th  j  k  l    \tBeginning and end of line\t[  ]\n\
  295. Word left and right\tH  L\t\tTop and bottom of file\t\tt  b\n\
  296. Page up and down\tJ  K\t\tDelete left and right\t\tX  x\n\
  297. Insert on and off\ti  ^L\t\tHelp on and off\t\t\t? \n\
  298. Save file\t\tF\t\tRedraw\t\t\t\tR\n\
  299. Quit\t\t\tQ\t\tFlip to EMACS-style\t\tZ\n\
  300. ....5...10....5...20....5...30....5...40....5...50....5...60....5...70....5...80";
  301.  
  302. keytable_t modual[] = {
  303.     { 'h', left },
  304.     { 'j', down },
  305.     { 'k', up },
  306.     { 'l', right },
  307.     { 'H', wleft },
  308.     { 'J', pgdown },
  309.     { 'K', pgup },
  310.     { 'L', wright },
  311.     { '[', lnbegin },
  312.     { ']', lnend },
  313.     { 't', top },
  314.     { 'b', bottom },
  315.     { 'i', insert_mode },
  316.     { 'x', delete },
  317.     { 'X', backsp },
  318.     { 'F', file },
  319.     { 'R', redraw },
  320.     { 'Q', quit },
  321.     { 'Z', flip },
  322.     { '?', help },
  323.     { 0, movegap }
  324. };
  325.  
  326. #ifdef POSIX
  327.  
  328. #include <termios.h>
  329.  
  330. /*
  331.  *    Set the desired input mode.
  332.  *
  333.  *    FALSE enables immediate character processing (disable signals 
  334.  *    and line processing.)  TRUE enables line processing and signals
  335.  *    (disables immediate character processing).  In either case flow 
  336.  *    control (XON/XOFF) is still active.  
  337.  *
  338.  *    If the termios function calls fail, then fall back on using 
  339.  *    CURSES' raw()/noraw() functions; however flow control will be 
  340.  *    affected.
  341.  */
  342. void
  343. lineinput(bf)
  344. int bf;
  345. {
  346.     int error;
  347.     struct termios term;
  348.     error = tcgetatt